﻿using System;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;
using System.Globalization;
using System.Transactions;

//自定义命名空间
using DreamCube.Foundation.Basic.Cache;
using DreamCube.Foundation.Basic.Enums;
using DreamCube.Foundation.Basic.Objects.EqualityComparers;

namespace DreamCube.Framework.DataAccess.Basic
{
    /// <summary>
    /// 数据库基础对象
    /// </summary>
    public abstract partial class Database
    {
        #region "受保护的方法"

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="dbProviderFactory"></param>
        protected Database(String connectionString, DbProviderFactory dbProviderFactory)
        {
            if (String.IsNullOrEmpty(connectionString))
                throw new ArgumentException(Properties.Resources.ExceptionNullOrEmptyString, "connectionString");
            if (dbProviderFactory == null) throw new ArgumentNullException("dbProviderFactory");
            this.connectionStringStr = connectionString;
            this.dbProviderFactory = dbProviderFactory;
        }

        /// <summary>
        /// 返回命令参数的起始序号
        /// </summary>
        /// <returns></returns>
        protected virtual Int32 UserParametersStartIndex()
        {
            return 0;
        }

        /// <summary>
        /// 配置一个命令参数的属性值
        /// </summary>
        /// <param name="param"></param>
        /// <param name="name"></param>
        /// <param name="dbType"></param>
        /// <param name="size"></param>
        /// <param name="direction"></param>
        /// <param name="nullable">该值指示参数是否接受 null 值</param>
        /// <param name="precision">
        /// 获取或设置用来表示 Value 属性的最大位数。 
        /// Precision 属性由 SqlDbType 为 Decimal 的参数使用。 
        /// 不需要为输入参数指定 Precision 和 Scale 属性的值，因为可以从参数值推断它们的值。 
        /// 输出参数以及在您需要指定参数的完整元数据而不指示值时，
        /// 需要 Precision 和 Scale，例如指定一个具有特定精度和小数位数的空值。 
        /// </param>
        /// <param name="scale">获取或设置 Value 解析为的小数位数。 </param>
        /// <param name="sourceColumn">获取或设置源列的名称，该源列映射到 DataSet 并用于加载或返回 Value </param>
        /// <param name="sourceVersion">获取或设置在加载 Value 时要使用的 DataRowVersion。</param>
        /// <param name="value"></param>
        protected virtual void ConfigureParameter(DbParameter param,
                                                  String name,
                                                  DbType? dbType,
                                                  Int32? size,
                                                  ParameterDirection direction,
                                                  Boolean nullable,
                                                  Byte precision,
                                                  Byte scale,
                                                  String sourceColumn,
                                                  DataRowVersion sourceVersion,
                                                  Object value)
        {
            if (dbType != null) param.DbType = dbType.Value;
            if (size.HasValue) param.Size = size.Value;
            param.Value = value ?? DBNull.Value;
            param.Direction = direction;
            param.IsNullable = nullable;
            param.SourceColumn = sourceColumn;
            param.SourceVersion = sourceVersion;
        }

        /// <summary>
        /// 创建一个命令参数对象
        /// </summary>
        /// <param name="name"></param>
        /// <param name="dbType"></param>
        /// <param name="size"></param>
        /// <param name="direction"></param>
        /// <param name="nullable"></param>
        /// <param name="precision">Precision 属性由 SqlDbType 为 Decimal 的参数使用。 </param>
        /// <param name="scale"></param>
        /// <param name="sourceColumn"></param>
        /// <param name="sourceVersion"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        protected DbParameter CreateParameter(String name,
                                              DbType? dbType,
                                              Int32? size,
                                              ParameterDirection direction,
                                              Boolean nullable,
                                              Byte precision,
                                              Byte scale,
                                              String sourceColumn,
                                              DataRowVersion sourceVersion,
                                              Object value)
        {
            DbParameter param = CreateParameter(name);
            ConfigureParameter(param, name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
            return param;
        }

        /// <summary>
        /// 创建一个命令参数对象
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected DbParameter CreateParameter(String name)
        {
            DbParameter param = dbProviderFactory.CreateParameter();
            param.ParameterName = this.FormatParameterName(name);
            return param;
        }

        /// <summary>
        /// 初始化命令对象（配置连接对象）
        /// </summary>
        /// <param name="command"></param>
        protected void InitalCommand(IDbCommand command)
        {
            if (command.Connection == null)
                command.Connection = this.CreateConnection(true);
        }

        #endregion
    }
}
